/*
 * Codegen.cpp
 *
 *  Created on: 1 Nov 2010
 *      Author: kn308
 */

#include "MAlice.hpp"
#include "Codegen.h"


static MAlice::Codegen* gCodegen = NULL;

namespace MAlice
{

Codegen::Codegen() :
	mContext(), mVars(), mTypeIds()
{
	mModule = new llvm::Module("MAlice", mContext);
	mBuilder = new llvm::IRBuilder<>(mContext);
	mVars.push_back(ScopeType());
}

Codegen* Codegen::get()
{
	if (!gCodegen)
		return gCodegen = new Codegen();
	else
		return gCodegen;
}

LLVMContext& Codegen::getContext()
{
	return mContext;
}

Builder* Codegen::getBuilder()
{
	return mBuilder;
}

Module* Codegen::getModule()
{
	return mModule;
}

Codegen::TypeIds& Codegen::getTypeIds()
{
	return mTypeIds;
}

Value* Codegen::getVar(const string& name)
{
	for (vector<ScopeType>::reverse_iterator i = mVars.rbegin(); i != mVars.rend(); i++)
	{
		if (Value* value = (*i) [name])
			return value;
	}

	return NULL;
}

void Codegen::pushVar(const string& name, Value* value)
{
	ScopeType& top = mVars.back();

	// ensure we are not redefining
	// if (top[name] != value) ;
	// {
	// 	throw runtime_error(name + " cannot be redefined!");
	// }

	top[name] = value;
}

void Codegen::pushScope()
{
	mVars.push_back(ScopeType());
}

void Codegen::popScope()
{
	// TODO the scope is exiting, we may want to add destructors
	// and invoke them at scope exit
	mVars.pop_back();
}

}
